/**
 *  core.h - Task management.
 *
 *  Copyright (C) 2008-2009 ZhangHu
 *  All rights reserved.
 *  E-MAIL: anmnmnly@gmail.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#ifndef __CORE_H__
#define __CORE_H__

#include "include/types.h"

#ifndef UNIT_DEBUG
#include "include/list.h"
#include "include/mem.h"
#include "include/irq.h"
#endif


#ifndef stk_t
#define stk_t    word_t
#endif

#define VERSION 100     /* Version of Bycoe 1.0.0*/

#define MAX_PRIO    64  /* the max priority of task.
                         * The greater value, the lower priority.
                         */
#define READY_NUM   8   /* the size of a array that used to find
                         * out the next running task
                         */

/* Task status */
#define T_READY  0x00   /* Task is ready */
#define T_BLOCK  0x01   /* Task is blocked */
#define T_SLEEP  0x02   /* Task is sleep */
#define T_DELAY  0x03   /* Task is delayed */


#define INIT_TASK_ID 99 /* The ID of initial task, which is the first task,
                         * and it was created after the initialization.
                         */
#define INIT_TASK_PRIO 0         /* The priority of initial task. */
#define INIT_TASK_STACK_SIZE 512 /* The stack length of initial task */

#define IDLE_TASK_ID 98 /* The ID of idle task, which been to survive
                         * until the shutdown, and it is running when
                         * there is no task runs.
                         */
#define IDLE_TASK_PRIO (MAX_PRIO - 1)
#define IDLE_TASK_STACK_SIZE 32


/* Task Control Block */
typedef struct task_ctrl_blk {
    void *context;      /* Pointer to context of task */
    void *pstart;       /* Pointer to the first address of task space */

    list_t link;        /* All tasks in a queue linked with this member */

    word_t id;          /* Task ID */
    uword_t prio;       /* Task priority */

    uword_t slice_time; /* Slice time */
    uword_t exe_time;   /* Executed time */
    word_t delay_time;  /* Delayed time */
    uword_t status;     /* Status, such as ready, delay, block as so on */
    slist_t sem_link;   /* A sigle list poiter to a semaphore gained by task */
    list_t task_link;   /* All tasks linked with this member */
} tcb_t;

extern uword_t get_isr_num(void); /* Get the interrupted source number */
extern void Main(void);   /* A routine that users start to write their codes */

/* The following routines are internal. Applications don't use them. */
void add_tcb_rdy(tcb_t *ptcb);      /* Add a TCB to ready queue */
list_t *del_tcb_rdy(tcb_t *ptcb);   /* Delete a TCB from ready queue */

void add_tcb_sleep(tcb_t *ptcb);    /* Add a TCB to sleep queue */

void lock_schedule(void);
void unlock_schedule(void);
uword_t if_isr(void);        /* To determine whether the current context
                              * is in interruption state or not.
                              */
uword_t get_clock(void);     /* Get the number of clock count */
tcb_t *current(void);        /* Get the TCB of current task. */

void scheduler(void);        /* Scheduler the core of task management */
void sysinit(void);          /* initialize function of Bycore */
void systick(void);          /* The heart of Bycore, in fact, it is a
                              * interruption handle routine of a timer.
                              */

/* Application Program Interfaces */

#define osLockSchedule() lock_schedule()
#define osUnLockSchedule() unlock_schedule()

/* osInitTask - It initializes a task with some parameters */
void osInitTask(void(*pTask)(),     /* Pointer to entry address of task */
                word_t TaskID,      /* Task ID */
                uword_t Prio,       /* Task priority */
                uword_t Time,       /* Task slice time */
                uword_t StkSize);   /* The size of stack */

/* osCreateTask - It initializes a task with some parameters.
 *    The differece between osCreateTask() and osInitTask()
 *    is that the former needs transfer a TCB and a stack space.
 */
void osCreateTask(void(*pTask)(),   /* Pointer to entry address of task */
                  tcb_t *pTcb,      /* Pointer to TCB of task */
                  word_t TaskID,    /* Task ID */
                  uword_t Prio,     /* Task priority */
                  uword_t Time,     /* Task slice time */
                  stk_t *pStk,      /* Pointer to stack space */
                  uword_t StkSize); /* The size of stack */

void osChgPrio(uword_t NewPrio);/* Change the priority of a task */
void osSleep(void);             /* Make a task to sleep */
void osWakeUp(word_t TaskID);   /* Wake up a sleep task */
void osWait(uword_t DelayTime); /* Make a task to been delayed for while */
void osKill(void);              /* Finish a life of a task */
uword_t osVersion(void);        /* Get the current version of Bycore */
list_t *osGetTaskHead(void);    /* Get the head of task list */
list_t *osGetSleepHead(void);   /* Get the head sleep queue */
list_t *osGetDelayHead(void);   /* Get the head delay queue */


#endif

